package xj.graph2d.shapes.uml;

import static javax.swing.SwingConstants.LEFT;
import static javax.swing.SwingConstants.VERTICAL;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import xj.graph2d.DrawShape;
import xj.graph2d.GraphNodeBase;
import xj.graph2d.Label;
import xj.graph2d.TextShape;
import xj.graph2d.shapes.BoxLabel;
import xj.graph2d.shapes.block.BlockShape;
import xj.graph2d.shapes.block.SimpleStatementShape;
import xj.graph2d.shapes.block.StatementShape;
import xj.graph2d.template.UMLStateDiagramTemplate;
import xj.meta.ModelElement;
import xj.model.uml.State;

import static xj.graph2d.template.VisualClassTemplate.OPER_BG;
import static xj.graph2d.template.VisualClassTemplate.OPER_FG;

public class UMLStateUtil {

  // shape/box --> model
  public static void getActions(State state, DrawShape actionBox) {
    if (state != null) {
      String entryAction = null;
      String exitAction = null;
      String doAction = null;
      if (actionBox instanceof BoxLabel) {
	BoxLabel box = (BoxLabel) actionBox;
	Iterator iter = box.allShapes();
	while (iter.hasNext()) {
	  Object o = iter.next();
	  if (o instanceof Label) {
	    String act = ((Label) o).getText();
	    if (act.startsWith("entry/")) {
	      entryAction = act.substring(6).trim();
	    } else if (act.startsWith("exit/")) {
	      exitAction = act.substring(5).trim();
	    } else if (act.startsWith("do/")) {
	      doAction = act.substring(3).trim();
	    } else {
	      if (entryAction == null) { 
		entryAction = act; 
	      }
	      
	      // internal transitions

	    }
	  }
	}
      } else if (actionBox instanceof BlockShape) {
	BlockShape block = (BlockShape) actionBox; 
	List<StatementShape> slist = block.getAllStatements();
	if (slist != null) { 
	  for (int i = 0; i < slist.size(); i++) {
	    StatementShape s = slist.get(i);
	    if (s instanceof SimpleStatementShape) { 
	      SimpleStatementShape s0 = (SimpleStatementShape) s;
	      String act = s0.getText();
	      if (act.startsWith("entry/")) {
		entryAction = act.substring(6).trim();
	      } else if (act.startsWith("exit/")) {
		exitAction = act.substring(5).trim();
	      } else if (act.startsWith("do/")) {
		doAction = act.substring(3).trim();
	      } else {
		if (entryAction == null) { 
		  entryAction = act; 
		}
		
		// internal transitions
		
	      }
	    }
	  }
	}
      }
      state.setEntryActionBody(entryAction);
      state.setExitActionBody(exitAction);
      state.setDoActionBody(doAction);
    }
  }

  // model --> shape/box
  public static DrawShape setActions(State state, DrawShape actionBox) {
    if (state != null) {
      String entryAction = state.getEntryActionBody();
      String exitAction = state.getExitActionBody();
      String doAction = state.getDoActionBody();
      boolean hasAction = false;
      if (actionBox instanceof BoxLabel) { 
	BoxLabel box = (BoxLabel) actionBox; 
	TextShape text = null;
	if (box != null) {
	  box.removeAllShapes();
	}
	if (box == null) {
	  box = new BoxLabel(VERTICAL, LEFT);
	  box.setMovable(false);
	}
	box.setDisplayName("Action");
	if (entryAction != null) {
	  entryAction = entryAction.trim();
	  if (entryAction.length() > 0) {
	    addActionText(box, "entry/" + entryAction);
	    hasAction = true;
	  }
	}
	if (exitAction != null) {
	  exitAction = exitAction.trim();
	  if (exitAction.length() > 0) {
	    addActionText(box, "exit/" + exitAction);
	    hasAction = true;
	  }
	}
	if (doAction != null) {
	  doAction = doAction.trim();
	  if (doAction.length() > 0) {
	    addActionText(box, "do/" + doAction);
	    hasAction = true;
	  }
	}

	if (!hasAction) {
	  text = template.makeContentText(null, "action", false,
					  UMLStateDiagramTemplate.ACTION_FONT,
					  UMLStateDiagramTemplate.ACTION_COLOR);
	  box.addShape(text);
	}
	
	box.doLayout();
      } else if (actionBox instanceof BlockShape) {
	BlockShape block = (BlockShape) actionBox;
	block.removeAllStatements();

	if (entryAction != null) {
	  entryAction = entryAction.trim();
	  if (entryAction.length() > 0) {
	    addActionStatement(block, "entry/" + entryAction);
	    hasAction = true;
	  }
	}
	if (exitAction != null) {
	  exitAction = exitAction.trim();
	  if (exitAction.length() > 0) {
	    addActionStatement(block, "exit/" + exitAction);
	    hasAction = true;
	  }
	}
	if (doAction != null) {
	  doAction = doAction.trim();
	  if (doAction.length() > 0) {
	    addActionStatement(block, "do/" + doAction);
	    hasAction = true;
	  }
	}

	if (!hasAction) {
	  addActionStatement(block, null);
	}

	block.positionSubNodes(true);

	/*
	boolean fit = block.isFitted();
	block.setFitted(true);
	block.doLayout();
	block.setFitted(fit);
	*/
      }

    }
    
    return actionBox; 
  }

  public static void addActionText(BoxLabel box, String str) {
    if (box != null) {
      TextShape text = null;
      if (template != null) {
	text = template.makeContentText(str, "action", false,
					UMLStateDiagramTemplate.ACTION_FONT,
					UMLStateDiagramTemplate.ACTION_COLOR);
      } else {
	text = new TextShape(str);
      }
      text.setDisplayName("Action");
      text.setDetachable(false);
      text.setScalable(false);
      text.setMovable(true);
      text.setSticky(true);
      box.addShape(text);
    }
  }

  public static void addActionStatement(BlockShape block, String str) {
    if (block != null) {
      if (template != null) { 
	SimpleStatementShape stmt = 
	  template.makeElementShape(SimpleStatementShape.ACTION,  "Action", "action", OPER_FG, OPER_BG);
	stmt.setText(str);
	block.addShape(stmt);
      }
    }
  }

  public static void initStyle(Map iconMap, UMLStateDiagramTemplate template) {
    UMLStateUtil.template = template;
  }

  public static boolean isInitialState(GraphNodeBase state) {
    if (state != null) { 
      ModelElement model = state.getModel();
      if (model instanceof State) { 
	State s = (State) model;
	return (s.getType() == State.StateType.Initial_State);
      }
    }
    return false;
  }

  public static  boolean isFinalState(GraphNodeBase state) {
    if (state != null) { 
      ModelElement model = state.getModel();
      if (model instanceof State) { 
	State s = (State) model;
	return (s.getType() == State.StateType.Final_State);
      }
    }
    return false; 
  }

  protected static UMLStateDiagramTemplate template = null;

}
